/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.uc.controller;

import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.domain.vo.GroupRoleUserTree;
import com.xy.biz.uc.domain.bo.UserBO;
import com.xy.biz.uc.domain.converter.UserConverter;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.enums.UserTypeEnum;
import com.xy.biz.uc.domain.query.UserCodeQuery;
import com.xy.biz.uc.domain.query.UserIdQuery;
import com.xy.biz.uc.domain.query.UserQuery;
import com.xy.biz.uc.domain.req.*;
import com.xy.biz.uc.domain.resp.CurrentUserResponse;
import com.xy.biz.uc.domain.resp.SaveUserResponse;
import com.xy.biz.uc.service.UploadFileService;
import com.xy.biz.uc.service.UserService;
import com.xy.lang.domain.KeyValue;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.util.DesensitizeUtils;
import com.xy.lang.validation.SaveChecks;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.util.BeanUtilsEx;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

import static com.xy.biz.uc.domain.req.IsInRoleRequest.Ownership.ONE_IN_ROLE;
import static com.xy.biz.uc.domain.req.IsInRoleRequest.Ownership.ONLY_ONE_ROLE;

/**
 *
 *
 * @author zsp
 * @date 2020-8-19
 */
@Slf4j
@RestController
@RequestMapping("/api/uc/user")
public class UserController implements UserClient {

    @Autowired
    private UserService userService;

    @Autowired
    private UploadFileService uploadFileService;


    @Override
    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_by_user_code")
    public Result<SaveUserResponse> saveUserByUserCode(@RequestBody SaveUserRequest request) {
        UserBO userBO = UserConverter.toBO(request);
        Result<?> saveUserResult = userService.saveUserByUserCode(userBO);
        if (saveUserResult.wasSuccess()) {
            return Result.success(BeanUtilsEx.copyProperties(userBO, () -> new SaveUserResponse()));
        }
        return Result.copy(saveUserResult);
    }

    @Override
    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_by_mobile")
    public Result<SaveUserResponse> saveUserByMobile(@RequestBody SaveUserRequest request) {
        UserBO userBO = UserConverter.toBO(request);
        Result<?> saveUserResult = userService.saveUserByMobile(userBO);
        if (saveUserResult.wasSuccess()) {
            return Result.success(BeanUtilsEx.copyProperties(userBO, () -> new SaveUserResponse()));
        }
        return Result.copy(saveUserResult);
    }

    @Override
    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_email")
    public Result<SaveUserResponse> saveUserByEmail(@RequestBody SaveUserRequest request) {
        UserBO userBO = UserConverter.toBO(request);
        Result<?> saveUserResult = userService.saveUserByEmail(userBO);
        if (saveUserResult.wasSuccess()) {
            return Result.success(BeanUtilsEx.copyProperties(userBO, () -> new SaveUserResponse()));
        }
        return Result.copy(saveUserResult);
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update")
    public Result<?> updateUser(@RequestBody SaveUserRequest request) {
        userService.updateUser(UserConverter.toBO(request));
        return Result.success();
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/lock")
    public Result<?> lockUser(@RequestBody LockUserRequest request) {
        return Result.success(userService.lockUser(UserConverter.toBO(request)));
    }

    @ApiOperation("修改用户基本信息")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update_user_base_info")
    @Override
    public Result<?> updateUserBaseInfo(@RequestBody SaveUserRequest request) {
        userService.updateUserBaseInfo(UserConverter.toBO(request));
        return Result.success();
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update_role")
    public Result<?> updateUserRole(@RequestBody SaveUserRequest request) {
        UserBO found = userService.getUser(UserIdQuery.builder().userIdList(Arrays.asList(request.getUserId())).build());
        if (found == null) {
            return Result.ofNotFound("未找到", request.getUserId());
        }
        found.setRoleIdList(request.getRoleIdList());
        userService.updateUser(found);
        return Result.success();
    }

    @Validatable
    @PostMapping(value = "/delete")
    public Result<?> deleteUser(@RequestBody GetUserRequest request) {
        userService.deleteUser(request.getUserId());
        return Result.success();
    }

    @Override
    @Validatable
    @PostMapping(value = "/get")
    public Result<UserDTO> getUser(@RequestBody GetUserRequest request) {
        return Result.success(
                UserConverter.toDTO(userService.getUser(
                        UserIdQuery.builder().withRole(request.isWithRole()).withUserGroup(request.isWithUserGroup()).build().addUserId(request.getUserId()))));
    }

    @Override
    @PostMapping(value = "/has_permission")
    public Result<Boolean> hasPermission() {
        return Result.success(userService.hasPermission());
    }

    @Override
    @Validatable
    @PostMapping(value = "/is_in_role")
    public Result<Boolean> isInRole(IsInRoleRequest request) {
        List<String> includeRoleCodeList = request.getIncludeRoleCodeList();
        if (CollectionUtils.isEmpty(includeRoleCodeList)) {
            return Result.ofBadRequest("包括的角色编码不能为空");
        }
        if (ONLY_ONE_ROLE.getCode() == request.getOwnership() && includeRoleCodeList.size() > 1) {
            return Result.ofBadRequest("仅限输入一个角色编码");
        }
        List<String> excludeRoleCodeList = request.getExcludeRoleCodeList();
        if (includeRoleCodeList.size() == 1) {
            if (ONLY_ONE_ROLE.getCode() == request.getOwnership()) {
                return Result.success(userService.isInRole(includeRoleCodeList.get(0), excludeRoleCodeList, true));
            } else if (ONE_IN_ROLE.getCode() == request.getOwnership()) {
                return Result.success(userService.isInRole(includeRoleCodeList.get(0), excludeRoleCodeList, false));
            } else {
                return Result.ofBadRequest("输入了错误的角色关系");
            }
        } else {
            if (ONLY_ONE_ROLE.getCode() == request.getOwnership()) {
                return Result.ofBadRequest("输入了错误的角色关系");
            } else if (ONE_IN_ROLE.getCode() == request.getOwnership()) {
                return Result.success(userService.isInRole(includeRoleCodeList, excludeRoleCodeList, false));
            } else {
                return Result.success(userService.isInRole(includeRoleCodeList, excludeRoleCodeList, true));
            }
        }
    }

    /**
     * 根据名字返回用户信息
     * @param request
     */
    @Override
    public Result<UserDTO> getUserByUserName(@RequestBody GetUserByNameRequest request) {
        return Result.success(
                UserConverter.toDTO(userService.getUserByUserName(
                        UserQuery.builder().withRole(request.isWithRole()).withUserGroup(request.isWithUserGroup()).userName(request.getUserName()).build())));
    }

    @Override
    public Result<List<UserDTO>> getUserByUserNameS(@RequestBody Collection<String> collection) {
        return Result.success(
                UserConverter.toDTO(userService.getUserByUserNameS(collection)));
    }

    @ApiOperation("获取用户基本信息")
    @Validatable
    @PostMapping(value = "/get_user_update")
    public Result<?> getUserFormUpdate() {
        return Result.success(userService.getUser(UserIdQuery.builder().build().addUserId(UserContextHolder.getUserId())));
    }

    @PostMapping(value = "/get_current")
    public Result<CurrentUserResponse> getCurrentUser() {
        Long userId = UserContextHolder.getUserId();
        if (null == userId) {
            return Result.fail(Result.UNAUTHORIZED);
        }
        CurrentUserResponse currentUserResponse = UserConverter.toCurrentUserResponse(userService.getUser(
                UserIdQuery.builder()
                        .userIdList(Arrays.asList(userId))
                        .withRole(true)
                        .withUserGroup(true)
                        .withResource(true)
                        .build()));
        return Result.success(currentUserResponse);
    }

    @Override
    public Result<UserDTO> getUserByUserCode(@RequestBody GetUserByUserCodeRequest request) {
        return Result.success(UserConverter.toDTO(userService.getUserByUserCode(
                BeanUtilsEx.copyProperties(request, () -> new UserCodeQuery()))));
    }

    @Override
    @PostMapping(value = "/list_by_id")
    public Result<List<UserDTO>> listUserById(@RequestBody Collection<Long> collection) {
        return Result.success(UserConverter.toDTO(userService.listUserById(UserIdQuery.builder().userIdList(new ArrayList<>(collection)).withUserGroup(true).build())));
    }

    @Override
    public Result<Collection<Long>> listUserIdByUserGroupId(Collection<Long> collection) {
        return Result.success(userService.listUserIdByUserGroupId(collection));
    }

    @Override
    @PostMapping(value = "/list")
    public Result<List<UserDTO>> listUser(@RequestBody ListUserRequest request) {
        return Result.success(UserConverter.toDTO(userService.listUser(UserConverter.toQuery(request))));
    }

    @PostMapping(value = "/list_users")
    public Result<GroupRoleUserTree> listUsers(@RequestBody ListUserRequest request) {
        GroupRoleUserTree groupRoleUserTree = userService.listUsers(request);
        return Result.success(groupRoleUserTree);
    }

    @ApiOperation("根据用户名模糊搜索用户")
    @Validatable
    @PostMapping(value = "/search_user")
    public Result<Page<UserBO>> searchUser(@RequestBody SearchUserRequest request) {
        UserQuery userQuery = UserConverter.toQuery(request);
        List<UserBO> userBOS = userService.searchUser(userQuery);
        int count = userService.searchCountUser(userQuery);
        return Result.success(new Page<>(userBOS, count));
    }

    @PostMapping(value = "/count")
    public Result<Integer> countUser(@RequestBody ListUserRequest request) {
        return Result.success(userService.countUser(UserConverter.toQuery(request)));
    }

    @PostMapping(value = "/page")
    public Result<Page<UserDTO>> pageUser(@RequestBody ListUserRequest request) {
        UserQuery query = UserConverter.toQuery(request);
        List<UserDTO> list = UserConverter.toDTO(userService.listUser(query));
        if (UserTypeEnum.CUSTOMER.equalsTo(query.getType()) && !CollectionUtils.isEmpty(list)) {
            list.forEach(e -> {
                e.setUserName(DesensitizeUtils.desensitizeName(e.getUserName()));
                e.setMobile(DesensitizeUtils.desensitizePhone(e.getMobile(), false));
                e.setEmail(DesensitizeUtils.desensitizeEmail(e.getEmail()));
            });
        }
        int count = userService.countUser(query);
        return Result.success(new Page<>(list, count));
    }

    @PostMapping(value = "/list_item_by_role_id")
    public Result<List<KeyValue<Long, String>>> listUserItemByRoleId(@RequestBody Collection<Long> collection) {
        List<UserBO> userBOList = userService.listUserByRoleId(collection);
        if (CollectionUtils.isEmpty(userBOList)) {
            return Result.success(Collections.emptyList());
        }
        return Result.success(userBOList.stream().map(e -> new KeyValue<>(e.getUserId(), e.getUserName()))
                .collect(Collectors.toList()));
    }

    @Validatable
    @PostMapping(value = "/list_role_id")
    public Result<List<Long>> listRoleIdByUserId(@RequestBody GetUserRequest request) {
        return Result.success(userService.listRoleIdByUserId(request.getUserId()));
    }

    @Validatable
    @PostMapping(value = "/save_user_group_user")
    public Result<?> saveUserGroupUser(@RequestBody SaveUserGroupUserRequest request) {
        return Result.success(userService.saveOrUpdateUserGroupUser(request.getUserGroupId(), request.getUserId()));
    }

    @Validatable
    @PostMapping(value = "/delete_user_group_user")
    public Result<?> deleteUserGroupUser(@RequestBody GetUserRequest request) {
        return Result.success(userService.deleteUserGroupUser(request.getUserId()));
    }

    @Validatable
    @PostMapping(value = "/get_user_group_id")
    public Result<Long> getUserGroupId(@RequestBody GetUserRequest request) {
        return Result.success(userService.getUserGroupId(request.getUserId()));
    }

    @ApiOperation("用户头像上传")
    @Validatable
    @PostMapping("upload_head_portrait")
    Result<?> uploadHeadPortrait(@RequestParam("file") MultipartFile file) {
        return uploadFileService.uploadHeadPortrait(file);
    }

    @ApiOperation("用户头像获取")
    @Validatable
    @PostMapping("get_user_avatar")
    Result<?> getUserAvatar() {
        return userService.getUserAvatar();
    }

    @ApiOperation("用户头像修改")
    @Validatable
    @PostMapping("set_user_avatar")
    Result<?> setUserAvatar(@RequestBody SaveUserAvatarRequest saveUserAvatarRequest) {
        return userService.setUserAvatar(saveUserAvatarRequest.getAvatar());
    }

    @ApiOperation("获取用户名称")
    @Validatable
    @PostMapping(value = "/getUserName")
    public Result<?> getUserName(@RequestBody GetUserRequest getUserRequest) {
        return Result.success(UserConverter.toUserNameResponse(userService.getUser(UserIdQuery.builder().build().addUserId(getUserRequest.getUserId()))));
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/27 18:18
     * @param request
     * @return com.xy.lang.domain.Result<java.util.List < UserBO>>
     * @description 获取部门下所有人员
     */
    @PostMapping(value = "/list_user_by_group")
    @Validatable
    @Override
    public Result<List<UserDTO>> listUserByUserGroup(@RequestBody ListUserGroupByIdsRequest request) {
        return Result.success(UserConverter.toDTO(userService.listUserByUserGroup(request.getGroupIds())));
    }

    @ApiOperation("根据用户名/部门/角色/模糊搜索用户")
    @Validatable
    @PostMapping(value = "/search_user_by_keyword")
    public Result<List<UserBO>> searchUserByKeyword(@RequestBody SearchUserRequest request) {
        List<UserBO> userBOS = userService.searchUserByKeyword(request);
        return Result.success(userBOS);
    }

    @ApiOperation("获取所以没有部门的人")
    @Validatable
    @PostMapping(value = "/get_all_no_group_user")
    public Result<?> getAllNoGroupUser() {
        return Result.success(userService.getAllNoGroupUser());
    }

    @ApiOperation("获取当前部门下的员工")
    @Validatable
    @PostMapping(value = "/get_users_by_group_id")
    public Result<?> getUsersByGroupId(@RequestBody GetUserGroupRequest request) {
        return Result.success(userService.getUsersByGroupId(request));
    }

    @ApiOperation("删除部门下员工")
    @Validatable
    @PostMapping(value = "/remove_user_group_user_rel")
    public Result<?> removeUserGroupUserRel(@RequestBody RemoveUserGroupUserRelRequest request) {
        return Result.success(userService.removeUserGroupUserRel(request));
    }

    @ApiOperation("根据角色Code查询此角色下的所有用户")
    @Validatable
    @PostMapping(value = "/search_user_by_code")
    public Result<List<UserBO>> searchUserByCode(@RequestBody SearchUserByCodeRequest request) {
        List<UserBO> userBOS = userService.searchUserByCode(request);
        return Result.success(userBOS);
    }

}
